热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

更多|表里_busybox的实现原理分析(C语言实现简易版的busybox)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了busybox的实现原理分析(C语言实现简易版的busybox)相关的知识,希望对你有一定的参考价值。1、li

篇首语:本文由编程笔记#小编为大家整理,主要介绍了busybox的实现原理分析(C语言实现简易版的busybox)相关的知识,希望对你有一定的参考价值。



1、linux中实现命令的两种方式

1.1、命令都是单独的可执行程序

aston:~$ ls -l /bin/ls
-rwxr-xr-x 1 root root 138208 28 2022 /bin/ls
aston:~$
aston:~$ ls -l /bin/mkdir
-rwxr-xr-x 1 root root 68096 28 2022 /bin/mkdir
aston:~$
aston:~$ file /bin/ls
/bin/ls: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=897f49cafa98c11d63e619e7e40352f855249c13, for GNU/Linux 3.2.0, stripped


(1)在linux的根文件系统中,系统自带的命令放在"/bin、/sbin"目录中,用户的命令放在"/usr/bin、/usr/sbin"目录中;
(2)用"ls -l"可知每个命令都是二进制文件,用"file"命令查看可知每个命令都是可执行文件;
(3)命令都是单独的可执行程序,这种方式一般都是Ubuntu、Centos、服务器的linux系统采用,部署在硬件资源比较充足的设备里;



1.2、命令是指向busybox的符号链接



(1)用"ls -l"可知每个命令都是符号链接,指向busybox;
(2)这种方式一般是嵌入式设备采用;



1.3、两种实现方式的对比



(1)每个命令都是单独的可执行程序:这种方式要求的资源更多,但是命令支持的功能也更丰富;
(2)用符号链接和busybox实现命令:busybox占用的空间明显小于所有单独命令可执行程序占用空间之和,节省更多的资源,但是busybox的命令都是裁剪过的,只支持命令中常用的选项;
(3)busybox适合嵌入式设备,支持必要的命令,而且占用的空间小,嵌入式设备flash和内存一般都不富裕;
(4)命令是单独可执行程序的方式:更适合在电脑、服务器上运行的linux系统,flash和内存等硬件资源都比较充裕,更注重性能和命令的完整;



2、busybox介绍

2.1、为什么需要busybox



(1)busybox集成了常用的所有命令,可以很方便的构建文件系统。假设现在要构建文件系统,如果没有busybox,则需要去下载"ls、cd、mkdir······"每个命令的源码再编译,工作量很大且很繁琐;
(2)busybox高度可裁剪,需要支持什么命令就配置busybox编译哪些命令的源码,有效减小busybox的体积,节省空间;



2.2、busybox的源码获取



官网地址:www.busybox.net



2.3、busybox的两种使用方式



(1)符号链接:建立符号链接指向busybox,为每个命令建立一个符号链接;
(2)直接调用busybox,比如:"busybox ls"的效果和直接执行"ls"命令是相同的;



3、C语言实现简易版busybox

3.1、源码

#include
#include
#include
//计算数组的成员个数
#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
//实现ls命令功能
int my_ls_main(int argc, char * argv[])

char bufCmd[256] = 0;
sprintf(bufCmd, "ls %s", argv[1]);
system(bufCmd);
return 0;

//实现mkdir命令功能
int my_mkdir_main(int argc, char * argv[])

char bufCmd[256] = 0;
sprintf(bufCmd, "mkdir %s", argv[1]);
system(bufCmd);
return 0;

//busybox的说明函数
int my_help_main(int argc, char * argv[])

printf("busybox only support commond:ls and mkdir\\n");
return 0;

//支持的命令列表
const char *applet_names[] =

"my_ls",
"my_mkdir",
"--help",
"-h"
;
//每个命令对应的实现函数,顺序要和applet_names数组的顺序一一对应
int (*const applet_main[])(int argc, char * argv[]) =

my_ls_main,
my_mkdir_main,
my_help_main,
my_help_main,
;
int main(int argc, char * argv[])

int i = 0;
char *cmdBuf = malloc(256);
int start_index = 0;
memset(cmdBuf, 0, sizeof(cmdBuf));
//打印接收到的命令
#if 0
while(i < argc)

printf("argv[%d] &#61; %s \\n", i, argv[i]);
i&#43;&#43;;

#endif
//如果是直接调用的busybox需要特殊处理
if(strcmp(argv[0], "my_busybox") &#61;&#61; 0)

start_index &#61; 1;

//在支持的命令列表里查找是否支持该命令
for(i &#61; 0; i < ARRAY_SIZE(applet_names); i&#43;&#43;)

if (strcmp(argv[start_index], applet_names[i]) &#61;&#61; 0)

applet_main[i](argc, argv);
break;


//查找不到输入的命令则不支持该命令
if(i &#61;&#61; ARRAY_SIZE(applet_names))

printf("command not found\\n");
return -1;

return 0;


3.2、代码的编译和使用

[root#]$ ls -l
total 16
-rwxr-xr-x 1 310793 domain_users 8352 Nov 15 16:25 my_busybox
lrwxrwxrwx 1 310793 domain_users 10 Nov 15 16:25 my_ls -> my_busybox
lrwxrwxrwx 1 310793 domain_users 10 Nov 15 16:26 my_mkdir -> my_busybox
-rwxrw---- 1 310793 domain_users 1857 Nov 15 16:31 test.c


(1)为了避免与系统中的busybox冲突&#xff0c;将可执行程序命名为my_busybox&#xff1b;
(2)本简易版busybox仅支持ls和mkdir命令&#xff0c;所以创建my_ls和my_mkdir命令执行my_busybox&#xff1b;
(3)将代码所在目录导出到环境变量PATH中&#xff0c;可以自动查找到刚才构建的命令(export PATH&#61;命令所在路径:$PATH);



3.3、代码执行效果

[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$ gcc test.c -o my_busybox
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$ my_ls ./
my_busybox my_ls my_mkdir test.c
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$ my_mkdir 112233
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$ my_ls ./
112233 my_busybox my_ls my_mkdir test.c
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$ my_busybox my_ls ./
112233 my_busybox my_ls my_mkdir test.c
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$ my_busybox -h
busybox only support commond:ls and mkdir
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$
[310793&#64;yanfa204_ubuntu18-jk128:weops 222]$ my_busybox --help
busybox only support commond:ls and mkdir

4、busybox实现框架分析


(1)busybox是个可执行程序&#xff0c;程序入口是main函数&#xff0c;在appletlib.c文件中&#xff1b;
(2)在main中只是实现逻辑控制&#xff0c;并不执行具体的功能&#xff0c;会把输入的指令进行解析&#xff0c;查找指令对应的函数去执行&#xff1b;
(3)在代码中有两个重要的数组&#xff0c;applet_main是函数指针数组&#xff0c;里面是每个命令对应的函数的函数指针&#xff0c;applet_names是保存的命令的字符串&#xff0c;两个数组的元素是一一对应的&#xff1b;
(4)将传递进来的命令先和applet_names数组进行比对&#xff0c;如果匹配上就拿数组下标去applet_main数组取的命令对应的函数并执行&#xff1b;
(5)每个命令都有对应的函数&#xff0c;比如&#xff1a;ls对应"ls_main"函数&#xff0c;cd命令对应"cd_main"函数&#xff1b;



推荐

再难的项目都是基础知识的复杂运用&#xff0c;基础是最重要的。给大家推荐一个学校嵌入式知识的网站&#xff0c;博主在大学时候学习嵌入式知识、找工作的时候都在用这个网站&#xff0c;网站里有C语言、Linux等等的笔试题、面试常问问题等等知识&#xff0c;无论是学习基础知识、面试刷题、交流工作经验都是不错的选择。大家一起进步&#xff0c;欢迎留言交流。
链接&#xff1a;学习神器跳转



推荐阅读
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 如何基于ggplot2构建相关系数矩阵热图以及一个友情故事
    本文介绍了如何在rstudio中安装ggplot2,并使用ggplot2构建相关系数矩阵热图。同时,通过一个友情故事,讲述了真爱难觅的故事背后的数据量化和皮尔逊相关系数的概念。故事中的小伙伴们在本科时参加各种考试,其中有些沉迷网络游戏,有些热爱体育,通过他们的故事,展示了不同兴趣和特长对学习和成绩的影响。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • ubuntu用sqoop将数据从hive导入mysql时,命令: ... [详细]
  • 如何搭建Java开发环境并开发WinCE项目
    本文介绍了如何搭建Java开发环境并开发WinCE项目,包括搭建开发环境的步骤和获取SDK的几种方式。同时还解答了一些关于WinCE开发的常见问题。通过阅读本文,您将了解如何使用Java进行嵌入式开发,并能够顺利开发WinCE应用程序。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • 分享css中提升优先级属性!important的用法总结
    web前端|css教程css!importantweb前端-css教程本文分享css中提升优先级属性!important的用法总结微信门店展示源码,vscode如何管理站点,ubu ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了在多平台下进行条件编译的必要性,以及具体的实现方法。通过示例代码展示了如何使用条件编译来实现不同平台的功能。最后总结了只要接口相同,不同平台下的编译运行结果也会相同。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
author-avatar
小啊丌-619
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有